package com.ld.shieldsb.common.core.util.pwdchecker.impl;

import com.ld.shieldsb.common.core.model.Result;
import com.ld.shieldsb.common.core.util.pwdchecker.PwdChecker;

/**
 * 包含大写字母、小写字母、数字、特殊符号（不是字母，数字，下划线，汉字的字符）的【默认8位及以上】密码校验器
 * 
 * @author <a href="mailto:donggongai@126.com" target="_blank">吕凯</a>
 * @date 2020年9月7日 上午11:55:12
 *
 */
public class AlphanumericSymbolPwdChecker implements PwdChecker {
    private Integer minLength = 8;
    private Integer maxLength = null;
    // 包含大写字母、小写字母、数字、特殊符号（不是字母，数字，下划线，汉字的字符）的8位以上组合
    /*
     * 思路：
      
     1、排除大写字母（A-Z）、小写字母包含下划线（a-z）、数字(0-9)、特殊符号包含下划线(\W_)中1种组合、2种组合、3种组合，那么就只剩下4种都包含的组合了
    　　2、表达式为：^(?![A-Za-z0-9]+$)(?![a-z0-9\\W]+$)(?![A-Za-z\\W]+$)(?![A-Z0-9\\W]+$)[a-zA-Z0-9\\W]{8,}$
    　　3、拆分解释：其中（2）-（6）运用了零宽断言、环视等正则功能
    　　　　（1）^匹配开头
    　　　　（2）(?![A-Za-z0-9]+$)匹配后面不全是（大写字母或小写字母或数字）的位置，排除了（大写字母、小写字母、数字）的1种2种3种组合
    　　　　（3）(?![a-z0-9\\W]+$)同理，排除了（小写字母、数字、特殊符号）的1种2种3种组合
    　　　　（4）(?![A-Za-z\\W]+$)同理，排除了（大写字母、小写字母、特殊符号）的1种2种3种组合
    　　　　（5）(?![A-Z0-9\\W]+$)同理，排除了（大写字母、数组、特殊符号）的1种2种3种组合
    　　　　（6）[a-zA-Z0-9\\W]匹配（小写字母或大写字母或数字或特殊符号）因为排除了上面的组合，所以就只剩下了4种都包含的组合了
    　　　　（7）{8,}8位以上
    　　　　（8）$匹配字符串结尾*/
    private String strongPwdPattern = "^(?![A-Za-z0-9]+$)(?![a-z0-9\\W_]+$)(?![A-Za-z\\W_]+$)(?![A-Z0-9\\W_]+$)[a-zA-Z0-9\\W_]{%s,%s}$";

    public AlphanumericSymbolPwdChecker() {
        strongPwdPattern = String.format(strongPwdPattern, minLength, maxLength == null ? "" : maxLength);
    }

    public AlphanumericSymbolPwdChecker(Integer minLength, Integer maxLength) {
        this.minLength = minLength;
        this.maxLength = maxLength;
        strongPwdPattern = String.format(strongPwdPattern, minLength, maxLength == null ? "" : maxLength);
    }

    @Override
    public Result checkIsSafe(String newpwd) {
        Result result = new Result();
        result.setSuccess(true);
        if (newpwd == null) {
            result.setSuccess(false);
            result.setMessage("密码不能为空！");
            return result;
        }
        if (newpwd.length() < minLength) { // 不少于 位
            result.setSuccess(false);
            result.setMessage(String.format("密码长度不能少于%s位！", minLength));
            return result;
        }
        if (maxLength != null && newpwd.length() > maxLength) { // 不大于8位
            result.setSuccess(false);
            result.setMessage(String.format("密码长度不能大于%s位！", maxLength));
            return result;
        }
        if (!newpwd.matches(strongPwdPattern)) {
            result.setSuccess(false);
            String msg = String.format("密码需要是包含大写字母、小写字母、数字、特殊符号（不是字母，数字，下划线，汉字的字符）的%s位以上", minLength);
            if (maxLength != null) { // 不大于 位
                msg += String.format("%s位以下", maxLength);
            }
            msg += "组合";
            result.setMessage(msg);
        }
        return result;
    }

    public Integer getMinLength() {
        return minLength;
    }

    public void setMinLength(Integer minLength) {
        this.minLength = minLength;
    }

    public Integer getMaxLength() {
        return maxLength;
    }

    public void setMaxLength(Integer maxLength) {
        this.maxLength = maxLength;
    }

}
